package com.geek.monitor;

import com.geek.monitor.event.HookEvent;
import com.geek.monitor.event.HookKeyboardEvent;
import com.geek.monitor.handler.KeyboardEventHandler;
import com.sun.jna.examples.win32.Kernel32;
import com.sun.jna.examples.win32.User32;
import com.sun.jna.examples.win32.User32.HHOOK;
import com.sun.jna.examples.win32.User32.KBDLLHOOKSTRUCT;
import com.sun.jna.examples.win32.User32.LowLevelKeyboardProc;
import com.sun.jna.examples.win32.User32.MSG;
import com.sun.jna.examples.win32.W32API.HMODULE;
import com.sun.jna.examples.win32.W32API.LRESULT;
import com.sun.jna.examples.win32.W32API.WPARAM;

/**
 * 监听键盘
 */
public class KeyboardHook implements Runnable{

	private static HHOOK hhk;
	private static LowLevelKeyboardProc keyboardHook;
	final static User32 lib = User32.INSTANCE;
	private boolean [] on_off=null;

	//短时间内按键只会触发一次
	private static final long PRESS_TIME_INTERVAL = 500;
	private long lastTime;

	private KeyboardEventHandler handler;

	public KeyboardHook(boolean [] on_off){
		this.on_off = on_off;
	}

	public KeyboardHook(boolean [] on_off, KeyboardEventHandler handler){
		this.on_off = on_off;
		this.handler = handler;
	}

	public void run() {

		HMODULE hMod = Kernel32.INSTANCE.GetModuleHandle(null);
		keyboardHook = new LowLevelKeyboardProc() {
			public LRESULT callback(int nCode, WPARAM wParam, KBDLLHOOKSTRUCT info) {
				if (on_off[0] == false) {
					System.exit(0);
				}
				//设置短时间内只会触发一遍
				if(System.currentTimeMillis() - lastTime > PRESS_TIME_INTERVAL){
					if (nCode >= 0) {
						if(handler != null){
							HookEvent event = new HookKeyboardEvent(info.vkCode);
							handler.handle(event);
						}else{
							System.out.println("没有相应的键盘输入消息处理器");
						}
					}

					lastTime = System.currentTimeMillis();
				}

				return lib.CallNextHookEx(hhk, nCode, wParam, info.getPointer());
			}
		};
		hhk = lib.SetWindowsHookEx(User32.WH_KEYBOARD_LL, keyboardHook, hMod, 0);
		int result;
		MSG msg = new MSG();
		while ((result = lib.GetMessage(msg, null, 0, 0)) != 0) {
			if (result == -1) {
				System.err.println("error in get message");
				break;
			} else {
				System.err.println("got message");
				lib.TranslateMessage(msg);
				lib.DispatchMessage(msg);
			}
		}
		lib.UnhookWindowsHookEx(hhk);
	}

}